package mapspinner.util.Vegetation;

import java.nio.FloatBuffer;
import java.util.Random;

import com.jme.bounding.BoundingBox;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.TexCoords;
import com.jme.scene.TriMesh;
import com.jme.scene.VBOInfo;
import com.jme.scene.geometryinstancing.GeometryBatchInstance;
import com.jme.scene.geometryinstancing.GeometryBatchInstanceAttributes;
import com.jme.scene.geometryinstancing.instance.GeometryBatchCreator;
import com.jme.scene.shape.Quad;
import com.jme.util.geom.BufferUtils;

public class BatchingGrass {

	private static ColorRGBA INSTANCE_COLOR = new ColorRGBA(0.3f, 0.4f, 0.2f, 1);

	private static VBOInfo DEFAULT_VBO_INFO = new VBOInfo(true);

	static {
		final FloatBuffer buff = BufferUtils.createVector2Buffer(4);
		buff.put(0).put(1);
		buff.put(0).put(0);
		buff.put(1).put(0);
		buff.put(1).put(1);
		VEGETATION_QUAD_TEXCOORDS = new TexCoords(buff);
	}
	private GeometryBatchCreator creator;
	public static TexCoords VEGETATION_QUAD_TEXCOORDS;
	private final Vector3f instanceTranslation = new Vector3f();
	private TriMesh mesh;

	private int verticeSize = 0;

	public BatchingGrass() {
	}

	public void batch() {
		// Create a TriMesh
		mesh = new TriMesh();
		mesh.setModelBound(new BoundingBox());

		// Create the batch's buffers
		mesh.setIndexBuffer(BufferUtils
				.createIntBuffer(creator.getNumIndices()));
		mesh.setVertexBuffer(BufferUtils.createVector3Buffer(creator
				.getNumVertices()));
		mesh.setNormalBuffer(BufferUtils.createVector3Buffer(creator
				.getNumVertices()));
		for (int normalIndex = 0; normalIndex < verticeSize; normalIndex++)
			BufferUtils.setInBuffer(Vector3f.UNIT_Y, mesh.getNormalBuffer(),
					normalIndex);

		mesh.setTextureCoords(new TexCoords(BufferUtils
				.createVector2Buffer(creator.getNumVertices())), 0);
		mesh.setColorBuffer(BufferUtils.createFloatBuffer(creator
				.getNumVertices() * 4));

		// Commit the instances to the mesh batch
		creator.commit(mesh);

		mesh.setVBOInfo(BatchingGrass.DEFAULT_VBO_INFO);
		mesh.updateModelBound();
		// mesh.lockMeshes();
		clean();
	}

	public void clean() {
		creator.clearInstances();
	}

	public TriMesh createMesh(final float scale, final int turnNumber,
			final short size) {
		final Quad q = new Quad("triMeshVegQuad", 1, 1);
		q.setTextureCoords(VEGETATION_QUAD_TEXCOORDS);

		creator = new GeometryBatchCreator();

		verticeSize = turnNumber * 4 * size;
		final Random rand = new Random();
		float orand = 0;
		float frand = 0;
		for (int x = 0; x < size; x++)
			for (int z = 0; z < size; z++) {
				orand = rand.nextFloat() - .5f;
				for (int i = 0; i < turnNumber; i++) {
					frand = rand.nextFloat() * 0.50f + 0.50f;
					final GeometryBatchInstance instance = new GeometryBatchInstance(
							q, new GeometryBatchInstanceAttributes(
									instanceTranslation.set(x * 2f + orand,
											scale / 2, z * 2f + orand),
									new Vector3f(scale * frand, scale * frand,
											scale * frand),
									new Quaternion().fromAngleAxis(
											(float) (Math.PI * 2 / turnNumber)
													* i, Vector3f.UNIT_Y),
									new ColorRGBA(
											BatchingGrass.INSTANCE_COLOR.r
													+ rand.nextFloat() / 10f,
											BatchingGrass.INSTANCE_COLOR.g
													+ rand.nextFloat() / 8f,
											BatchingGrass.INSTANCE_COLOR.b
													+ rand.nextFloat() / 8f,
											BatchingGrass.INSTANCE_COLOR.a)));

					creator.addInstance(instance);
				}
			}
		batch();
		return mesh;
	}

	public GeometryBatchCreator getCreator() {
		return creator;
	}

}